package com.changgou.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.entity.Result;
import com.changgou.goods.feign.SkuFeign;
import com.changgou.goods.pojo.Sku;
import com.changgou.search.dao.SkuEsMapper;
import com.changgou.search.pojo.SkuInfo;
import com.changgou.search.service.SkuService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SkuServiceImpl implements SkuService{

    @Autowired
    private SkuEsMapper skuEsMapper;

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public void importSku() {
        Result<List<Sku>> result = skuFeign.findByStatus("1");

        /*        Result<List<Sku>> result = skuFeign.findAll();*/

        List<SkuInfo> skuInfoList=  JSON.parseArray(JSON.toJSONString(result.getData()),SkuInfo.class);

        skuInfoList.forEach(item->{
            Map<String,Object> map = JSON.parseObject(item.getSpec(), Map.class);
            item.setSpecMap(map);
        });
        skuEsMapper.saveAll(skuInfoList);

    }

    @Override
    public Map search(Map<String, String> searchMap) {

        //1.获取关键字的值
        String keywords = searchMap.get("keywords");

        if (StringUtils.isEmpty(keywords)) {
            keywords = "华为";//赋值给一个默认的值
        }

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        HighlightBuilder.Field field = new HighlightBuilder.Field("name");

        field.preTags("<em style=\"color:red\">");

        field.postTags("</em>");

        field.fragmentSize(100);

        nativeSearchQueryBuilder.withHighlightFields(field);



        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("name",keywords));

        //商品分类分组
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategorygroup").field("categoryName").size(100));
        //品牌分组
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuBrandgroup").field("brandName").size(100));

        //设置分组条件 商品的规格
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuSpecgroup").field("spec.keyword").size(200));

        //构建分页查询
        Integer pageNum = 1;
        if (!StringUtils.isEmpty(searchMap.get("pageNum"))) {
            try {
                pageNum = Integer.valueOf(searchMap.get("pageNum"));
            } catch (NumberFormatException e) {
                e.printStackTrace();
                pageNum=1;
            }
        }
        Integer pageSize = 3;
        nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum - 1, pageSize));



        //构建排序查询
        String sortRule = searchMap.get("sortRule");
        String sortField = searchMap.get("sortField");
        if (!StringUtils.isEmpty(sortRule) && !StringUtils.isEmpty(sortField)) {
            nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(sortRule.equals("DESC") ? SortOrder.DESC : SortOrder.ASC));
        }

        //4.构建查询对象
        NativeSearchQuery query = nativeSearchQueryBuilder.build();


        AggregatedPage<SkuInfo> skuPage = elasticsearchTemplate.queryForPage(query, SkuInfo.class,
                new SearchResultMapper() {
                    @Override
                    public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
                        List<T> content = new ArrayList<>();
                        //如果没有结果返回为空
                        if (response.getHits() == null || response.getHits().getTotalHits() <= 0) {
                            return new AggregatedPageImpl<T>(content);
                        }
                        for (SearchHit searchHit : response.getHits()) {
                            String sourceAsString = searchHit.getSourceAsString();
                            SkuInfo skuInfo = JSON.parseObject(sourceAsString, SkuInfo.class);

                            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                            HighlightField highlightField = highlightFields.get("name");

                            //有高亮则设置高亮的值
                            if (highlightField != null) {
                                StringBuffer stringBuffer = new StringBuffer();
                                for (Text text : highlightField.getFragments()) {
                                    stringBuffer.append(text.string());
                                }
                                skuInfo.setName(stringBuffer.toString());
                            }
                            content.add((T) skuInfo);
                        }


                        return new AggregatedPageImpl<T>(content, pageable, response.getHits().getTotalHits(), response.getAggregations(), response.getScrollId());
                    }
                });

        List<String> categoryList = new ArrayList<>();
        if (StringUtils.isEmpty(searchMap.get("category"))) {
            categoryList = getStringsCategoryList(skuPage);
        }

        List<String> brandList = new ArrayList<>();
        if (StringUtils.isEmpty(searchMap.get("brand"))) {
            brandList = getStringsBrandList(skuPage);
        }

        Map<String, Set<String>> specList = getStringsSpecList(skuPage);

        //6.返回结果
        Map resultMap = new HashMap<>();
        resultMap.put("categoryList",categoryList); //分类数据
        resultMap.put("specList",specList); //规格数据
        resultMap.put("brandList ",brandList); //品牌数据
        resultMap.put("rows", skuPage.getContent()); //数据
        resultMap.put("total", skuPage.getTotalElements()); //总记录数
        resultMap.put("totalPages", skuPage.getTotalPages()); //总页数

        return resultMap;
    }

    private List<String> getStringsCategoryList(AggregatedPage<SkuInfo> skuPage) {
        StringTerms stringTerms = (StringTerms) skuPage.getAggregation("skuCategorygroup");

        List<String> categoryList = new ArrayList<>();

        if (stringTerms != null) {
            stringTerms.getBuckets().forEach(item -> {
                categoryList.add(item.getKeyAsString());
            });
        }
        return categoryList;
    }

    private List<String> getStringsBrandList(AggregatedPage<SkuInfo> skuPage) {
        StringTerms stringTerms = (StringTerms) skuPage.getAggregation("skuBrandgroup");

        List<String> brandList = new ArrayList<>();

        if (stringTerms != null) {
            stringTerms.getBuckets().forEach(item -> {
                brandList.add(item.getKeyAsString());
            });
        }
        return brandList;
    }

    private Map<String, Set<String>> getStringsSpecList(AggregatedPage<SkuInfo> skuPage) {
        StringTerms stringTerms = (StringTerms) skuPage.getAggregation("skuSpecgroup");

        List<String> specList = new ArrayList<>();

        if (stringTerms != null) {
            stringTerms.getBuckets().forEach(item -> {
                specList.add(item.getKeyAsString());
            });
        }

        Map<String, Set<String>> specMap = new HashMap<String, Set<String>>();
        specList.forEach(item->{
            Map<String,String> map = JSON.parseObject(item, Map.class);
            map.forEach((k,v)->{
                //获取当前规格名字对应的规格数据
                Set<String> set = specMap.get(k);
                if (set == null) {
                    set = new HashSet<>();
                }
                set.add(v);
                specMap.put(k, set);
            });
        });
        System.out.println(specMap);
        return specMap;
    }
}
